<template>
  <el-dialog 
    title="连接外部数据库" 
    v-model="visible" 
    width="800px" 
    append-to-body
    @close="handleClose"
  >
    <!-- 数据库连接配置 -->
    <el-card v-if="!connected" class="box-card" shadow="never">
      <template #header>
        <div class="card-header">
          <span>数据库连接配置</span>
        </div>
      </template>
      
      <el-form ref="configFormRef" :model="dbConfig" :rules="configRules" label-width="120px">
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="数据库类型" prop="dbType">
              <el-select v-model="dbConfig.dbType" placeholder="请选择数据库类型" style="width: 100%">
                <el-option
                  v-for="(label, value) in dbTypes"
                  :key="value"
                  :label="label"
                  :value="value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="主机地址" prop="host">
              <el-input v-model="dbConfig.host" placeholder="请输入主机地址" />
            </el-form-item>
          </el-col>
        </el-row>
        
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="端口号" prop="port">
              <el-input-number 
                v-model="dbConfig.port" 
                :min="1" 
                :max="65535" 
                placeholder="端口号"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="数据库名" prop="database">
              <el-input v-model="dbConfig.database" placeholder="请输入数据库名" />
            </el-form-item>
          </el-col>
        </el-row>
        
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="用户名" prop="username">
              <el-input v-model="dbConfig.username" placeholder="请输入用户名" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="密码" prop="password">
              <el-input 
                v-model="dbConfig.password" 
                type="password" 
                placeholder="请输入密码"
                show-password
              />
            </el-form-item>
          </el-col>
        </el-row>
        
        <el-row :gutter="20" v-if="dbConfig.dbType === 'postgresql' || dbConfig.dbType === 'oracle'">
          <el-col :span="12">
            <el-form-item label="模式名" prop="schema">
              <el-input v-model="dbConfig.schema" placeholder="请输入模式名(可选)" />
            </el-form-item>
          </el-col>
        </el-row>

        <el-row>
          <el-col :span="24">
            <el-form-item>
              <el-checkbox v-model="saveConnection">保存连接信息到本地缓存</el-checkbox>
              <el-button
                v-if="savedConnections.length > 0"
                type="text"
                @click="showSavedConnections = !showSavedConnections"
                style="margin-left: 10px"
              >
                {{ showSavedConnections ? '隐藏' : '显示' }}已保存的连接 ({{ savedConnections.length }})
              </el-button>
            </el-form-item>
          </el-col>
        </el-row>

        <!-- 已保存的连接列表 -->
        <el-row v-if="showSavedConnections && savedConnections.length > 0">
          <el-col :span="24">
            <el-card shadow="never" style="margin-bottom: 10px;">
              <template #header>
                <span>已保存的连接</span>
              </template>
              <div style="max-height: 200px; overflow-y: auto;">
                <div
                  v-for="(conn, index) in savedConnections"
                  :key="index"
                  style="display: flex; justify-content: space-between; align-items: center; padding: 8px 0; border-bottom: 1px solid #f0f0f0;"
                >
                  <div style="flex: 1; cursor: pointer;" @click="loadSavedConnection(conn)">
                    <div style="font-weight: bold;">{{ conn.name }}</div>
                    <div style="font-size: 12px; color: #666;">
                      {{ conn.dbType }} - {{ conn.host }}:{{ conn.port }}/{{ conn.database }}
                    </div>
                  </div>
                  <el-button
                    type="text"
                    size="small"
                    @click="deleteSavedConnection(index)"
                    style="color: #f56c6c;"
                  >
                    删除
                  </el-button>
                </div>
              </div>
            </el-card>
          </el-col>
        </el-row>
      </el-form>
      
      <div class="dialog-footer">
        <el-button @click="handleClose">取消</el-button>
        <el-button type="primary" @click="testConnection" :loading="testing">
          <el-icon><Connection /></el-icon>
          测试连接
        </el-button>
      </div>
    </el-card>
    
    <!-- 表列表 -->
    <div v-if="connected">
      <el-card class="box-card" shadow="never">
        <template #header>
          <div class="card-header">
            <span>数据库表列表</span>
            <el-button type="text" @click="disconnectDb">
              <el-icon><Close /></el-icon>
              断开连接
            </el-button>
          </div>
        </template>
        
        <!-- 搜索区域 -->
        <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
          <el-form-item label="表名称" prop="tableName">
            <el-input
              v-model="queryParams.tableName"
              placeholder="请输入表名称"
              clearable
              style="width: 200px"
              @keyup.enter="handleQuery"
            />
          </el-form-item>
          <el-form-item label="表描述" prop="tableComment">
            <el-input
              v-model="queryParams.tableComment"
              placeholder="请输入表描述"
              clearable
              style="width: 200px"
              @keyup.enter="handleQuery"
            />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
          </el-form-item>
        </el-form>
        
        <!-- 表格 -->
        <el-table 
          v-loading="loading" 
          :data="dbTableList" 
          @selection-change="handleSelectionChange"
          height="400px"
        >
          <el-table-column type="selection" width="55" align="center" />
          <el-table-column prop="tableName" label="表名称" :show-overflow-tooltip="true" />
          <el-table-column prop="tableComment" label="表描述" :show-overflow-tooltip="true" />
          <el-table-column prop="createTime" label="创建时间" width="180">
            <template #default="scope">
              <span>{{ parseTime(scope.row.createTime) }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="updateTime" label="更新时间" width="180">
            <template #default="scope">
              <span>{{ parseTime(scope.row.updateTime) }}</span>
            </template>
          </el-table-column>
        </el-table>
        
        <pagination
          v-show="total > 0"
          :total="total"
          v-model:page="queryParams.pageNum"
          v-model:limit="queryParams.pageSize"
          @pagination="getTableList"
        />
      </el-card>
    </div>
    
    <template #footer v-if="connected">
      <div class="dialog-footer">
        <el-button @click="handleClose">取消</el-button>
        <el-button type="primary" @click="handleImportTable" :loading="importing">
          导入选中表 ({{ selectedTables.length }})
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup name="ExternalDbDialog">
import { ref, reactive, onMounted, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Connection, Close, Search, Refresh } from '@element-plus/icons-vue'
import {
  testExternalDbConnection,
  listExternalDbTables,
  importExternalTables,
  getSupportedDbTypes
} from '@/api/tool/gen'
import { parseTime } from '@/utils/ruoyi'

const emit = defineEmits(['ok'])

// 响应式数据
const visible = ref(false)
const connected = ref(false)
const testing = ref(false)
const importing = ref(false)
const loading = ref(false)
const showSearch = ref(true)
const total = ref(0)
const saveConnection = ref(false)
const showSavedConnections = ref(false)
const savedConnections = ref([])

// 数据库类型
const dbTypes = ref({})

// 数据库配置
const dbConfig = reactive({
  dbType: 'mysql',
  host: 'localhost',
  port: 3306,
  database: '',
  username: '',
  password: '',
  schema: ''
})

// 查询参数
const queryParams = reactive({
  pageNum: 1,
  pageSize: 10,
  tableName: '',
  tableComment: ''
})

// 表格数据
const dbTableList = ref([])
const selectedTables = ref([])

// 缓存相关数据
const tableCache = ref({
  data: [], // 缓存的完整表格数据
  cacheKey: '', // 当前缓存的数据库连接标识
  isValid: false, // 缓存是否有效
  searchParams: { // 缓存时的搜索参数
    tableName: '',
    tableComment: ''
  }
})

// 表单验证规则
const configRules = {
  dbType: [{ required: true, message: '数据库类型不能为空', trigger: 'change' }],
  host: [{ required: true, message: '主机地址不能为空', trigger: 'blur' }],
  port: [{ required: true, message: '端口号不能为空', trigger: 'blur' }],
  database: [{ required: true, message: '数据库名不能为空', trigger: 'blur' }],
  username: [{ required: true, message: '用户名不能为空', trigger: 'blur' }],
  password: [{ required: true, message: '密码不能为空', trigger: 'blur' }]
}

// 表单引用
const configFormRef = ref()
const queryRef = ref()

/** 显示对话框 */
function show() {
  visible.value = true
  connected.value = false
  resetForm()
}

/** 重置表单 */
function resetForm() {
  if (configFormRef.value) {
    configFormRef.value.resetFields()
  }
  Object.assign(dbConfig, {
    dbType: 'mysql',
    host: 'localhost',
    port: 3306,
    database: '',
    username: '',
    password: '',
    schema: ''
  })

  dbTableList.value = []
  selectedTables.value = []
  total.value = 0
  clearTableCache()
}

/** 关闭对话框 */
function handleClose() {
  visible.value = false
  connected.value = false
  clearTableCache()
  resetForm()
}

/** 测试数据库连接 */
function testConnection() {
  if (!configFormRef.value) return

  configFormRef.value.validate(valid => {
    if (valid) {
      testing.value = true
      testExternalDbConnection(dbConfig).then(res => {
        if (res.code === 200) {
          ElMessage.success('连接成功')
          connected.value = true

          // 如果勾选了保存连接，则保存到本地缓存
          if (saveConnection.value) {
            saveConnectionToLocal()
          }

          getTableList()
        } else {
          ElMessage.error(res.msg || '连接失败')
        }
      }).catch(error => {
        ElMessage.error('连接失败: ' + error.message)
      }).finally(() => {
        testing.value = false
      })
    }
  })
}

/** 断开数据库连接 */
function disconnectDb() {
  connected.value = false
  dbTableList.value = []
  selectedTables.value = []
  clearTableCache()
}

/** 获取表列表 */
function getTableList() {
  const currentCacheKey = generateCacheKey()
  const currentSearchParams = {
    tableName: queryParams.tableName,
    tableComment: queryParams.tableComment
  }

  // 检查是否可以使用缓存
  if (canUseCache(currentCacheKey, currentSearchParams)) {
    // 使用缓存数据进行前端分页
    applyFrontendPagination()
    return
  }

  // 需要重新获取数据
  loading.value = true

  // 获取全量数据（不分页）
  const fullQueryParams = {
    pageNum: 1,
    pageSize: 5000, // 获取全量数据，设置一个合理的上限
    tableName: queryParams.tableName,
    tableComment: queryParams.tableComment
  }

  listExternalDbTables(dbConfig, fullQueryParams).then(res => {
    // 缓存完整数据
    tableCache.value = {
      data: res.rows || [],
      cacheKey: currentCacheKey,
      isValid: true,
      searchParams: { ...currentSearchParams }
    }

    // 应用前端分页
    applyFrontendPagination()

    // 如果数据量较大，给用户提示
    if (res.rows && res.rows.length >= 1000) {
      ElMessage.info(`已加载 ${res.rows.length} 个表，后续分页操作将在前端进行，提升响应速度`)
    }
  }).catch(error => {
    ElMessage.error('获取表列表失败: ' + error.message)
    // 清除无效缓存
    clearTableCache()
  }).finally(() => {
    loading.value = false
  })
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.pageNum = 1
  // 搜索参数变化时，需要重新获取数据
  clearTableCache()
  getTableList()
}

/** 重置按钮操作 */
function resetQuery() {
  if (queryRef.value) {
    queryRef.value.resetFields()
  }
  // 重置搜索参数时，清除缓存
  clearTableCache()
  handleQuery()
}

/** 多选框选中数据 */
function handleSelectionChange(selection) {
  selectedTables.value = selection.map(item => item.tableName)
}

/** 导入表操作 */
function handleImportTable() {
  if (selectedTables.value.length === 0) {
    ElMessage.warning('请选择要导入的表')
    return
  }

  ElMessageBox.confirm(
    `确认导入选中的 ${selectedTables.value.length} 个表吗？`,
    '提示',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(() => {
    importing.value = true
    const importData = {
      dbConfig: dbConfig,
      tableNames: selectedTables.value
    }

    importExternalTables(importData).then(res => {
      if (res.code === 200) {
        ElMessage.success(res.msg)
        visible.value = false
        clearTableCache() // 导入完成后清除缓存
        emit('ok')
      } else {
        ElMessage.error(res.msg || '导入失败')
      }
    }).catch(error => {
      ElMessage.error('导入失败: ' + error.message)
    }).finally(() => {
      importing.value = false
    })
  })
}

/** 生成缓存键 */
function generateCacheKey() {
  return `${dbConfig.dbType}_${dbConfig.host}_${dbConfig.port}_${dbConfig.database}_${dbConfig.username}`
}

/** 检查是否可以使用缓存 */
function canUseCache(currentCacheKey, currentSearchParams) {
  if (!tableCache.value.isValid || tableCache.value.cacheKey !== currentCacheKey) {
    return false
  }

  // 检查搜索参数是否一致
  const cachedParams = tableCache.value.searchParams
  return cachedParams.tableName === currentSearchParams.tableName &&
         cachedParams.tableComment === currentSearchParams.tableComment
}

/** 应用前端分页 */
function applyFrontendPagination() {
  const { pageNum, pageSize } = queryParams
  const startIndex = (pageNum - 1) * pageSize
  const endIndex = startIndex + pageSize

  // 从缓存数据中获取当前页数据
  dbTableList.value = tableCache.value.data.slice(startIndex, endIndex)
  total.value = tableCache.value.data.length
}

/** 清除表格缓存 */
function clearTableCache() {
  tableCache.value = {
    data: [],
    cacheKey: '',
    isValid: false,
    searchParams: {
      tableName: '',
      tableComment: ''
    }
  }
}

/** 获取支持的数据库类型 */
function loadDbTypes() {
  getSupportedDbTypes().then(res => {
    if (res.code === 200) {
      dbTypes.value = res.data
    }
  })
}

/** 保存连接信息到本地缓存 */
function saveConnectionToLocal() {
  try {
    const connectionName = `${dbConfig.dbType}-${dbConfig.host}-${dbConfig.database}`
    const connectionInfo = {
      name: connectionName,
      dbType: dbConfig.dbType,
      host: dbConfig.host,
      port: dbConfig.port,
      database: dbConfig.database,
      username: dbConfig.username,
      password: dbConfig.password, // 注意：实际项目中可能需要加密存储
      schema: dbConfig.schema,
      savedAt: new Date().toISOString()
    }

    // 检查是否已存在相同的连接
    const existingIndex = savedConnections.value.findIndex(conn =>
      conn.dbType === connectionInfo.dbType &&
      conn.host === connectionInfo.host &&
      conn.port === connectionInfo.port &&
      conn.database === connectionInfo.database &&
      conn.username === connectionInfo.username
    )

    if (existingIndex >= 0) {
      // 更新现有连接
      savedConnections.value[existingIndex] = connectionInfo
      ElMessage.success('连接信息已更新')
    } else {
      // 添加新连接
      savedConnections.value.push(connectionInfo)
      ElMessage.success('连接信息已保存')
    }

    // 保存到localStorage
    localStorage.setItem('external_db_connections', JSON.stringify(savedConnections.value))
  } catch (error) {
    ElMessage.error('保存连接信息失败: ' + error.message)
  }
}

/** 从本地缓存加载已保存的连接 */
function loadSavedConnectionsFromLocal() {
  try {
    const saved = localStorage.getItem('external_db_connections')
    if (saved) {
      savedConnections.value = JSON.parse(saved)
    }
  } catch (error) {
    console.error('加载已保存的连接失败:', error)
    savedConnections.value = []
  }
}

/** 加载选中的连接信息 */
function loadSavedConnection(connection) {
  Object.assign(dbConfig, {
    dbType: connection.dbType,
    host: connection.host,
    port: connection.port,
    database: connection.database,
    username: connection.username,
    password: connection.password,
    schema: connection.schema || ''
  })

  showSavedConnections.value = false
  ElMessage.success('连接信息已加载')
}

/** 删除已保存的连接 */
function deleteSavedConnection(index) {
  ElMessageBox.confirm(
    '确认删除这个已保存的连接吗？',
    '提示',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(() => {
    savedConnections.value.splice(index, 1)
    localStorage.setItem('external_db_connections', JSON.stringify(savedConnections.value))
    ElMessage.success('连接已删除')
  }).catch(() => {
    // 用户取消删除
  })
}

// 组件挂载时加载数据库类型和已保存的连接
onMounted(() => {
  loadDbTypes()
  loadSavedConnectionsFromLocal()
})

// 监听数据库类型变化，设置默认端口
watch(() => dbConfig.dbType, (newType) => {
  switch (newType) {
    case 'mysql':
      dbConfig.port = 3306
      break
    case 'postgresql':
      dbConfig.port = 5432
      break
    case 'oracle':
      dbConfig.port = 1521
      break
    case 'sqlserver':
      dbConfig.port = 1433
      break
  }
})

defineExpose({
  show
})
</script>

<style scoped>
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.dialog-footer {
  text-align: right;
  margin-top: 20px;
}

.box-card {
  margin-bottom: 20px;
}
</style>
